package org.jupiter.blog.service.service.impl;

import org.jupiter.blog.api.convertor.JupiterUrlResourceConvertor;
import org.jupiter.blog.api.domain.JupiterUrlResource;
import org.jupiter.blog.api.dto.JupiterUrlResourceDTO;
import org.jupiter.blog.service.mapper.JupiterUrlResourceMapper;
import org.jupiter.blog.service.service.JupiterUrlResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class JupiterUrlResourceServiceImpl implements JupiterUrlResourceService {

	@Autowired
	private JupiterUrlResourceMapper urlResourceMapper;

	@Autowired
	private JupiterUrlResourceConvertor urlResourceConvertor;

	@Override
	@Transactional
	public void createUrlResource(JupiterUrlResourceDTO dto) {
		JupiterUrlResource urlResource = urlResourceConvertor.toEntity(dto);
		if (!StringUtils.hasText(urlResource.getUuid())){
			urlResource.setUuid(UUID.randomUUID().toString());
		}
		urlResource.setCreateTime(LocalDateTime.now());
		urlResource.setUpdateTime(LocalDateTime.now());
		urlResourceMapper.insert(urlResource);
	}

	@Override
	@Transactional(readOnly = true)
	public JupiterUrlResourceDTO getById(String uuid) {
		JupiterUrlResource urlResource = urlResourceMapper.selectByUuid(uuid);
		return urlResourceConvertor.toDto(urlResource);
	}

	@Override
	@Transactional
	public void updateUrlResource(String uuid, JupiterUrlResourceDTO dto) {
		JupiterUrlResource urlResource = urlResourceConvertor.toEntity(dto);
		urlResource.setUuid(uuid);
		urlResource.setUpdateTime(LocalDateTime.now());
		urlResourceMapper.updateByUuidSelective(urlResource);
	}

	@Override
	@Transactional
	public void deleteUrlResource(String uuid) {
		urlResourceMapper.deleteByUuid(uuid);
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterUrlResourceDTO> getByPage(JupiterUrlResourceDTO queryDTO) {
		int offset = (queryDTO.getPage() - 1) * queryDTO.getSize();
		List<JupiterUrlResource> urlResources = urlResourceMapper.selectByPage(
				queryDTO.getUrl(),
				queryDTO.getMethod(),
				queryDTO.getModule(),
				offset,
				queryDTO.getSize()
		);
		return urlResources.stream()
				.map(urlResourceConvertor::toDto)
				.collect(Collectors.toList());
	}

	@Override
	@Transactional(readOnly = true)
	public long getCount(JupiterUrlResourceDTO queryDTO) {
		return urlResourceMapper.countByQuery(
				queryDTO.getUrl(),
				queryDTO.getMethod(),
				queryDTO.getModule()
		);
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterUrlResourceDTO> getAll() {
		List<JupiterUrlResource> urlResources = urlResourceMapper.selectAll();
		return urlResources.stream()
				.map(urlResourceConvertor::toDto)
				.collect(Collectors.toList());
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterUrlResourceDTO> getByModuleKey(String moduleKey) {
		List<JupiterUrlResource> urlResources = urlResourceMapper.selectByModule(moduleKey);
		return urlResources.stream()
				.map(urlResourceConvertor::toDto)
				.collect(Collectors.toList());
	}

	@Override
	@Transactional(readOnly = true)
	public JupiterUrlResourceDTO getByUrlAndMethod(String url, String method) {
		JupiterUrlResource urlResource = urlResourceMapper.selectByUrlAndMethod(url, method);
		return urlResourceConvertor.toDto(urlResource);
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterUrlResourceDTO> getActiveByModuleKey(String moduleKey) {
		List<JupiterUrlResource> urlResources = urlResourceMapper.selectActiveByModule(moduleKey);
		return urlResources.stream()
				.map(urlResourceConvertor::toDto)
				.collect(Collectors.toList());
	}

	@Override
	@Transactional(readOnly = true)
	public List<JupiterUrlResourceDTO> getAllActive() {
		List<JupiterUrlResource> urlResources = urlResourceMapper.selectActiveAll();
		return urlResources.stream()
				.map(urlResourceConvertor::toDto)
				.collect(Collectors.toList());
	}
}
